package com.hcms.admin.config;

import com.hcms.admin.filter.AuthenticationTokenFilter;
import com.hcms.admin.filter.VerificationCodeFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private CmsSecurityProperties cmsSecurityProperties;

    @Autowired(required = false)
    private VerificationCodeFilter verificationCodeFilter;

    @Autowired
    private AuthenticationTokenFilter authenticationTokenFilter;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //运行跨域请求的OPTIONS请求
        logger.info("Enable HttpMethod.OPTIONS request");
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();

        //安全路径白名单
        logger.info("Register the secure path whitelist");
        for (String url : cmsSecurityProperties.getIgnoredUrls()) {
            http.authorizeRequests().antMatchers(url).permitAll();
            logger.info("Registered url: {}", url);
        }

        //添加验证码过滤器
        if (verificationCodeFilter != null) {
            http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class);
        }

        //关闭跨站访问、不使用session
        http
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //
                .and()
                .formLogin()
                .loginProcessingUrl("/login").permitAll()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                //
                .and()
                .logout()
                .logoutSuccessHandler(logoutSuccessHandler)
                //自定义权限拒绝处理类
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint) //处理未登录异常
                .accessDeniedHandler(accessDeniedHandler) //处理无权限异常
                //设置请求身份认证
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                //添加自定义过滤器
                .and()
                .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
